/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { Arg, transBigInt32 } from './arg';
import { Reg } from './reg';
import { StackSlot } from './stack_solt';
import { GP, FP, PTR } from './symbols';
import { symbolName } from './util';
import { CCallCustom, ColdCCallCustom, PatchCustom, ShuffleCustom } from './custom';

const INST_COUNT_NUM_2: number = 2;
const INST_COUNT_NUM_3: number = 3;
const INST_COUNT_NUM_4: number = 4;
const INST_COUNT_NUM_5: number = 5;
const INST_COUNT_NUM_6: number = 6;

const INST_WIDTH_NUM_8: number = 8;
const INST_WIDTH_NUM_16: number = 16;
const INST_WIDTH_NUM_32: number = 32;
const INST_WIDTH_NUM_64: number = 64;

const INST_SOME_VALUE_2: number = 2;
const INST_SOME_VALUE_3: number = 3;
const INST_SOME_VALUE_4: number = 4;
const INST_SOME_VALUE_5: number = 5;
const INST_SOME_VALUE_6: number = 6;
const INST_SOME_VALUE_7: number = 7;
const INST_SOME_VALUE_8: number = 8;
const INST_SOME_VALUE_9: number = 9;
const INST_SOME_VALUE_10: number = 10;
const INST_SOME_VALUE_11: number = 11;
const INST_SOME_VALUE_12: number = 12;
const INST_SOME_VALUE_13: number = 13;
const INST_SOME_VALUE_14: number = 14;
const INST_SOME_VALUE_15: number = 15;
const INST_SOME_VALUE_16: number = 16;
const INST_SOME_VALUE_17: number = 17;
const INST_SOME_VALUE_18: number = 18;
const INST_SOME_VALUE_19: number = 19;
const INST_SOME_VALUE_20: number = 20;
const INST_SOME_VALUE_21: number = 21;
const INST_SOME_VALUE_22: number = 22;
const INST_SOME_VALUE_23: number = 23;
const INST_SOME_VALUE_24: number = 24;
const INST_SOME_VALUE_25: number = 25;
const INST_SOME_VALUE_26: number = 26;
const INST_SOME_VALUE_27: number = 27;
const INST_SOME_VALUE_28: number = 28;
const INST_SOME_VALUE_29: number = 29;
const INST_SOME_VALUE_30: number = 30;
const INST_SOME_VALUE_31: number = 31;
const INST_SOME_VALUE_32: number = 32;
const INST_SOME_VALUE_33: number = 33;
const INST_SOME_VALUE_34: number = 34;
const INST_SOME_VALUE_35: number = 35;
const INST_SOME_VALUE_36: number = 36;
const INST_SOME_VALUE_37: number = 37;
const INST_SOME_VALUE_38: number = 38;
const INST_SOME_VALUE_39: number = 39;
const INST_SOME_VALUE_40: number = 40;
const INST_SOME_VALUE_41: number = 41;
const INST_SOME_VALUE_42: number = 42;
const INST_SOME_VALUE_43: number = 43;
const INST_SOME_VALUE_44: number = 44;
const INST_SOME_VALUE_45: number = 45;
const INST_SOME_VALUE_46: number = 46;
const INST_SOME_VALUE_47: number = 47;
const INST_SOME_VALUE_48: number = 48;
const INST_SOME_VALUE_49: number = 49;
const INST_SOME_VALUE_50: number = 50;
const INST_SOME_VALUE_51: number = 51;
const INST_SOME_VALUE_52: number = 52;
const INST_SOME_VALUE_53: number = 53;
const INST_SOME_VALUE_54: number = 54;
const INST_SOME_VALUE_55: number = 55;
const INST_SOME_VALUE_56: number = 56;
const INST_SOME_VALUE_57: number = 57;
const INST_SOME_VALUE_58: number = 58;
const INST_SOME_VALUE_59: number = 59;
const INST_SOME_VALUE_60: number = 60;
const INST_SOME_VALUE_61: number = 61;
const INST_SOME_VALUE_62: number = 62;
const INST_SOME_VALUE_63: number = 63;
const INST_SOME_VALUE_64: number = 64;
const INST_SOME_VALUE_65: number = 65;
const INST_SOME_VALUE_66: number = 66;
const INST_SOME_VALUE_67: number = 67;
const INST_SOME_VALUE_68: number = 68;
const INST_SOME_VALUE_69: number = 69;
const INST_SOME_VALUE_70: number = 70;
const INST_SOME_VALUE_71: number = 71;
const INST_SOME_VALUE_72: number = 72;
const INST_SOME_VALUE_73: number = 73;
const INST_SOME_VALUE_74: number = 74;
const INST_SOME_VALUE_75: number = 75;
const INST_SOME_VALUE_76: number = 76;
const INST_SOME_VALUE_77: number = 77;
const INST_SOME_VALUE_78: number = 78;
const INST_SOME_VALUE_79: number = 79;
const INST_SOME_VALUE_80: number = 80;
const INST_SOME_VALUE_81: number = 81;
const INST_SOME_VALUE_82: number = 82;
const INST_SOME_VALUE_83: number = 83;
const INST_SOME_VALUE_84: number = 84;
const INST_SOME_VALUE_85: number = 85;
const INST_SOME_VALUE_86: number = 86;
const INST_SOME_VALUE_87: number = 87;
const INST_SOME_VALUE_88: number = 88;
const INST_SOME_VALUE_89: number = 89;
const INST_SOME_VALUE_90: number = 90;
const INST_SOME_VALUE_91: number = 91;
const INST_SOME_VALUE_92: number = 92;
const INST_SOME_VALUE_93: number = 93;
const INST_SOME_VALUE_94: number = 94;
const INST_SOME_VALUE_95: number = 95;
const INST_SOME_VALUE_96: number = 96;
const INST_SOME_VALUE_97: number = 97;
const INST_SOME_VALUE_98: number = 98;
const INST_SOME_VALUE_99: number = 99;
const INST_SOME_VALUE_100: number = 100;
const INST_SOME_VALUE_101: number = 101;
const INST_SOME_VALUE_102: number = 102;
const INST_SOME_VALUE_103: number = 103;
const INST_SOME_VALUE_104: number = 104;
const INST_SOME_VALUE_105: number = 105;
const INST_SOME_VALUE_106: number = 106;
const INST_SOME_VALUE_107: number = 107;
const INST_SOME_VALUE_108: number = 108;
const INST_SOME_VALUE_109: number = 109;
const INST_SOME_VALUE_110: number = 110;
const INST_SOME_VALUE_111: number = 111;
const INST_SOME_VALUE_112: number = 112;
const INST_SOME_VALUE_113: number = 113;
const INST_SOME_VALUE_114: number = 114;
const INST_SOME_VALUE_115: number = 115;
const INST_SOME_VALUE_116: number = 116;
const INST_SOME_VALUE_117: number = 117;
const INST_SOME_VALUE_118: number = 118;
const INST_SOME_VALUE_119: number = 119;
const INST_SOME_VALUE_120: number = 120;
const INST_SOME_VALUE_121: number = 121;
const INST_SOME_VALUE_122: number = 122;
const INST_SOME_VALUE_123: number = 123;
const INST_SOME_VALUE_124: number = 124;
const INST_SOME_VALUE_125: number = 125;
const INST_SOME_VALUE_126: number = 126;
const INST_SOME_VALUE_127: number = 127;
const INST_SOME_VALUE_128: number = 128;
const INST_SOME_VALUE_129: number = 129;
const INST_SOME_VALUE_130: number = 130;
const INST_SOME_VALUE_131: number = 131;
const INST_SOME_VALUE_132: number = 132;
const INST_SOME_VALUE_133: number = 133;

export class InstDateModel {
  role: string;
  type: string;
  width: number;
  constructor(role: string, type: string, width: number) {
    this.role = role;
    this.type = type;
    this.width = width;
  }
}

export class Inst {
  _opcode: string;

  get opcode(): string {
    return this._opcode;
  }
  set opcode(newValue: string) {
    this._opcode = newValue;
  }

  _args: Arg[] = new Array();
  patchHasNonArgEffects: boolean | null;

  extraEarlyClobberedRegs = new Set<Reg>();

  extraClobberedRegs = new Set<Reg>();

  get args(): Arg[] {
    return this._args;
  }

  set args(newValue: Arg[]) {
    this._args = newValue;
  }

  patchArgData: InstDateModel[] = new Array();

  constructor(opcode: string, args: Arg[] = new Array()) {
    this._opcode = opcode;
    this._args = args;
  }

  static emptyInst(): Inst {
    return new Inst(nop);
  }

  append(arg: Arg): void {
    this._args.push(arg);
  }

  clear(): void {
    this._opcode = nop;
    this._args = new Array();
  }

  getOpcode(): string {
    return this._opcode;
  }

  getArgs(): Arg[] {
    return this._args;
  }

  visitArg(index: number, fun: (arg: Arg, role: string, type: string, width: number) => Arg | null, args: InstDateModel): void {
    let replacement = fun(this._args[index], args.role, args.type, args.width);
    if (replacement !== null) {
      this._args[index] = replacement;
    }
  }

  forEachTmpFast(fun: (reg: Reg) => Reg | null): void {
    for (let i = 0; i < this._args.length; ++i) {
      let replacement = this._args[i].forEachTmpFast(fun);
      if (replacement !== null) {
        this._args[i] = replacement;
      }
    }
  }

  forEachArg(fun: (arg: Arg, role: string, type: string, width: number) => Arg | null): void {
    instForEachArg(this, fun);
  }

  forEachTmp(fun: (arg: Reg, role: string, type: string, width: number) => Reg | null): void {
    this.forEachArg((arg, role, type, width) => {
      return arg.forEachTmp(role, type, width, fun);
    });
  }

  forEach(thing: typeof StackSlot, fun: (value: StackSlot, role: string, type: string, width: number) => StackSlot | null): void {
    this.forEachArg((arg, role, type, width) => {
      return arg.forEach(thing, role, type, width, fun);
    });
  }

  static forEachDef(
    thing: typeof StackSlot,
    prevInst: Inst | null,
    nextInst: Inst | null,
    fun: (slot: StackSlot, role: string, type: string, width: number) => StackSlot | null): void {
    if (prevInst !== null) {
      prevInst.forEach(thing, (value, role, type, width) => {
        if (Arg.isLateDef(role)) {
          return fun(value, role, type, width);
        }
        return null;
      });
    }

    if (nextInst !== null) {
      nextInst.forEach(thing, (value, role, type, width) => {
        if (Arg.isEarlyDef(role)) {
          return fun(value, role, type, width);
        }
        return null;
      });
    }
  }

  static forEachDefWithExtraClobberedRegs(
    thing: typeof StackSlot,
    prevInst: Inst | null,
    nextInst: Inst | null,
    fun: (slot: StackSlot, role: string, type: string, width: number) => StackSlot | null): void {
    this.forEachDef(thing, prevInst, nextInst, fun);

    let regDefRole: string = '';
    let reportReg: (reg: Reg) => StackSlot | null = ((reg: Reg) => {
      let type = reg.isGPR ? GP : FP;
      return fun(thing.extract(reg), regDefRole, type, Arg.conservativeWidth(type));
    });

    if (prevInst !== null && prevInst._opcode === patch) {
      regDefRole = Arg.def;
      prevInst.extraClobberedRegs.forEach(reg => {
        reportReg(reg);
      });
    }

    if (nextInst !== null && nextInst._opcode === patch) {
      regDefRole = Arg.earlyDef;
      nextInst.extraEarlyClobberedRegs.forEach(reg => {
        reportReg(reg);
      });
    }
  }

  get hasNonArgEffects(): boolean {
    return instHasNonArgEffects(this);
  }

  hash(): number {
    let result = opcodeCode(this._opcode);
    for (let arg of this._args) {
      result += arg.hash();
      result = transBigInt32(result);
      result |= 0;
    }
    return result >>> 0;
  }

  toString(): string {
    return `${symbolName(this._opcode)}`;
  }
}

export let nop: string = 'Nop';
export let add32: string = 'Add32';
export let add8: string = 'Add8';
export let add16: string = 'Add16';
export let add64: string = 'Add64';
export let addDouble: string = 'AddDouble';
export let addFloat: string = 'AddFloat';
export let sub32: string = 'Sub32';
export let sub64: string = 'Sub64';
export let subDouble: string = 'SubDouble';
export let subFloat: string = 'SubFloat';
export let neg32: string = 'Neg32';
export let neg64: string = 'Neg64';
export let negateDouble: string = 'NegateDouble';
export let mul32: string = 'Mul32';
export let mul64: string = 'Mul64';
export let multiplyAdd32: string = 'MultiplyAdd32';
export let multiplyAdd64: string = 'MultiplyAdd64';
export let multiplySub32: string = 'MultiplySub32';
export let multiplySub64: string = 'MultiplySub64';
export let multiplyNeg32: string = 'MultiplyNeg32';
export let multiplyNeg64: string = 'MultiplyNeg64';
export let div32: string = 'Div32';
export let div64: string = 'Div64';
export let mulDouble: string = 'MulDouble';
export let mulFloat: string = 'MulFloat';
export let divDouble: string = 'DivDouble';
export let divFloat: string = 'DivFloat';
export let x86ConvertToDoubleWord32: string = 'X86ConvertToDoubleWord32';
export let x86ConvertToQuadWord64: string = 'X86ConvertToQuadWord64';
export let x86Div32: string = 'X86Div32';
export let x86Div64: string = 'X86Div64';
export let lea: string = 'Lea';
export let and32: string = 'And32';
export let and64: string = 'And64';
export let andDouble: string = 'AndDouble';
export let andFloat: string = 'AndFloat';
export let xorDouble: string = 'XorDouble';
export let xorFloat: string = 'XorFloat';
export let lshift32: string = 'Lshift32';
export let lshift64: string = 'Lshift64';
export let rshift32: string = 'Rshift32';
export let rshift64: string = 'Rshift64';
export let urshift32: string = 'Urshift32';
export let urshift64: string = 'Urshift64';
export let or32: string = 'Or32';
export let or64: string = 'Or64';
export let xor32: string = 'Xor32';
export let xor64: string = 'Xor64';
export let not32: string = 'Not32';
export let not64: string = 'Not64';
export let absDouble: string = 'AbsDouble';
export let absFloat: string = 'AbsFloat';
export let ceilDouble: string = 'CeilDouble';
export let ceilFloat: string = 'CeilFloat';
export let floorDouble: string = 'FloorDouble';
export let floorFloat: string = 'FloorFloat';
export let sqrtDouble: string = 'SqrtDouble';
export let sqrtFloat: string = 'SqrtFloat';
export let convertInt32ToDouble: string = 'ConvertInt32ToDouble';
export let convertInt64ToDouble: string = 'ConvertInt64ToDouble';
export let convertInt32ToFloat: string = 'ConvertInt32ToFloat';
export let convertInt64ToFloat: string = 'ConvertInt64ToFloat';
export let countLeadingZeros32: string = 'CountLeadingZeros32';
export let countLeadingZeros64: string = 'CountLeadingZeros64';
export let convertDoubleToFloat: string = 'ConvertDoubleToFloat';
export let convertFloatToDouble: string = 'ConvertFloatToDouble';
export let move: string = 'Move';
export let swap32: string = 'Swap32';
export let swap64: string = 'Swap64';
export let move32: string = 'Move32';
export let storeZero32: string = 'StoreZero32';
export let signExtend32ToPtr: string = 'SignExtend32ToPtr';
export let zeroExtend8To32: string = 'ZeroExtend8To32';
export let signExtend8To32: string = 'SignExtend8To32';
export let zeroExtend16To32: string = 'ZeroExtend16To32';
export let signExtend16To32: string = 'SignExtend16To32';
export let moveFloat: string = 'MoveFloat';
export let moveDouble: string = 'MoveDouble';
export let moveZeroToDouble: string = 'MoveZeroToDouble';
export let move64ToDouble: string = 'Move64ToDouble';
export let move32ToFloat: string = 'Move32ToFloat';
export let moveDoubleTo64: string = 'MoveDoubleTo64';
export let moveFloatTo32: string = 'MoveFloatTo32';
export let load8: string = 'Load8';
export let store8: string = 'Store8';
export let load8SignedExtendTo32: string = 'Load8SignedExtendTo32';
export let load16: string = 'Load16';
export let load16SignedExtendTo32: string = 'Load16SignedExtendTo32';
export let store16: string = 'Store16';
export let compare32: string = 'Compare32';
export let compare64: string = 'Compare64';
export let test32: string = 'Test32';
export let test64: string = 'Test64';
export let compareDouble: string = 'CompareDouble';
export let compareFloat: string = 'CompareFloat';
export let branch8: string = 'Branch8';
export let branch32: string = 'Branch32';
export let branch64: string = 'Branch64';
export let branchTest8: string = 'BranchTest8';
export let branchTest32: string = 'BranchTest32';
export let branchTest64: string = 'BranchTest64';
export let branchDouble: string = 'BranchDouble';
export let branchFloat: string = 'BranchFloat';
export let branchAdd32: string = 'BranchAdd32';
export let branchAdd64: string = 'BranchAdd64';
export let branchMul32: string = 'BranchMul32';
export let branchMul64: string = 'BranchMul64';
export let branchSub32: string = 'BranchSub32';
export let branchSub64: string = 'BranchSub64';
export let branchNeg32: string = 'BranchNeg32';
export let branchNeg64: string = 'BranchNeg64';
export let moveConditionally32: string = 'MoveConditionally32';
export let moveConditionally64: string = 'MoveConditionally64';
export let moveConditionallyTest32: string = 'MoveConditionallyTest32';
export let moveConditionallyTest64: string = 'MoveConditionallyTest64';
export let moveConditionallyDouble: string = 'MoveConditionallyDouble';
export let moveConditionallyFloat: string = 'MoveConditionallyFloat';
export let moveDoubleConditionally32: string = 'MoveDoubleConditionally32';
export let moveDoubleConditionally64: string = 'MoveDoubleConditionally64';
export let moveDoubleConditionallyTest32: string = 'MoveDoubleConditionallyTest32';
export let moveDoubleConditionallyTest64: string = 'MoveDoubleConditionallyTest64';
export let moveDoubleConditionallyDouble: string = 'MoveDoubleConditionallyDouble';
export let moveDoubleConditionallyFloat: string = 'MoveDoubleConditionallyFloat';
export let jump: string = 'Jump';
export let ret32: string = 'Ret32';
export let ret64: string = 'Ret64';
export let retFloat: string = 'RetFloat';
export let retDouble: string = 'RetDouble';
export let oops: string = 'Oops';
export let shuffle: string = 'Shuffle';
export let patch: string = 'Patch';
export let cCall: string = 'CCall';
export let coldCCall: string = 'ColdCCall';

export function instForEachArg(inst: Inst, fun: (arg: Arg, role: string, type: string, width: number) => Arg | null): void {
  //    let replacement
  switch (inst._opcode) {
    case nop:
      break;
    case add32:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_32));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case add8:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_8));
      inst.visitArg(1, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_8));
      break;
    case add16:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_16));
      inst.visitArg(1, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_16));
      break;
    case add64:
      switch (inst._args.length) {
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_64));
          break;
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, GP, INST_WIDTH_NUM_64));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case addDouble:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, FP, INST_WIDTH_NUM_64));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case addFloat:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_32));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, FP, INST_WIDTH_NUM_32));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case sub32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_32));
      break;
    case sub64:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_64));
      break;
    case subDouble:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, FP, INST_WIDTH_NUM_64));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case subFloat:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_32));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, FP, INST_WIDTH_NUM_32));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case neg32:
      inst.visitArg(0, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_32));
      break;
    case neg64:
      inst.visitArg(0, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_64));
      break;
    case negateDouble:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(0, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
      break;
    case mul32:
      switch (inst._args.length) {
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_32));
          break;
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case mul64:
      switch (inst._args.length) {
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_64));
          break;
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, GP, INST_WIDTH_NUM_64));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case multiplyAdd32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case multiplyAdd64:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.def, GP, INST_WIDTH_NUM_64));
      break;
    case multiplySub32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case multiplySub64:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.def, GP, INST_WIDTH_NUM_64));
      break;
    case multiplySub32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case multiplySub64:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_64));
      break;
    case div32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case div64:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, GP, INST_WIDTH_NUM_64));
      break;
    case mulDouble:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, FP, INST_WIDTH_NUM_64));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case mulFloat:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_32));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, FP, INST_WIDTH_NUM_32));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case divDouble:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, FP, INST_WIDTH_NUM_64));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case divFloat:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_32));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, FP, INST_WIDTH_NUM_32));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case x86ConvertToDoubleWord32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case x86ConvertToQuadWord64:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, GP, INST_WIDTH_NUM_64));
      break;
    case x86Div32:
      inst.visitArg(0, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      break;
    case x86Div64:
      inst.visitArg(0, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      break;
    case lea:
      inst.visitArg(0, fun, new InstDateModel(Arg.useAddr, GP, PTR));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, GP, PTR));
      break;
    case and32:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_32));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case and64:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, GP, INST_WIDTH_NUM_64));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_64));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case andDouble:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, FP, INST_WIDTH_NUM_64));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case andFloat:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_32));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, FP, INST_WIDTH_NUM_32));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case xorDouble:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, FP, INST_WIDTH_NUM_64));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case xorFloat:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_32));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, FP, INST_WIDTH_NUM_32));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case lshift32:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_32));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case lshift64:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_64));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_64));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case rshift32:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_32));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case rshift64:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_64));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_64));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case urshift32:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_32));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case urshift64:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_64));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_64));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case or32:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_32));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case or64:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, GP, INST_WIDTH_NUM_64));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_64));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case xor32:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_32));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case xor64:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.def, GP, INST_WIDTH_NUM_64));
          break;
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_64));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case not32:
      switch (inst._args.length) {
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
          break;
        case 1:
          inst.visitArg(0, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_32));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case not64:
      switch (inst._args.length) {
        case INST_COUNT_NUM_2:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(1, fun, new InstDateModel(Arg.def, GP, INST_WIDTH_NUM_64));
          break;
        case 1:
          inst.visitArg(0, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_64));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case absDouble:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
      break;
    case absFloat:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_32));
      break;
    case ceilDouble:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
      break;
    case ceilFloat:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_32));
      break;
    case floorDouble:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
      break;
    case floorFloat:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_32));
      break;
    case sqrtDouble:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
      break;
    case sqrtFloat:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_32));
      break;
    case convertInt32ToDouble:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
      break;
    case convertInt64ToDouble:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
      break;
    case convertInt32ToFloat:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_32));
      break;
    case convertInt64ToFloat:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_32));
      break;
    case countLeadingZeros32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case countLeadingZeros64:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, GP, INST_WIDTH_NUM_64));
      break;
    case convertDoubleToFloat:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_32));
      break;
    case convertFloatToDouble:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
      break;
    case move:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, PTR));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, GP, PTR));
      break;
    case swap32:
      inst.visitArg(0, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_32));
      break;
    case swap64:
      inst.visitArg(0, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_64));
      break;
    case move32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case storeZero32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      break;
    case signExtend32ToPtr:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, GP, PTR));
      break;
    case zeroExtend8To32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_8));
      inst.visitArg(1, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case signExtend8To32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_8));
      inst.visitArg(1, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case zeroExtend16To32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_16));
      inst.visitArg(1, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case signExtend16To32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_16));
      inst.visitArg(1, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case moveFloat:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_32));
      break;
    case moveDouble:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
      break;
    case moveZeroToDouble:
      inst.visitArg(0, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
      break;
    case move64ToDouble:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
      break;
    case move32ToFloat:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_32));
      break;
    case moveDoubleTo64:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, GP, INST_WIDTH_NUM_64));
      break;
    case moveFloatTo32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, GP, INST_WIDTH_NUM_32));
      break;
    case load8:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_8));
      inst.visitArg(1, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case store8:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_8));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, GP, INST_WIDTH_NUM_8));
      break;
    case load8SignedExtendTo32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_8));
      inst.visitArg(1, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case load16:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_16));
      inst.visitArg(1, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case load16SignedExtendTo32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_16));
      inst.visitArg(1, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case store16:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_16));
      inst.visitArg(1, fun, new InstDateModel(Arg.def, GP, INST_WIDTH_NUM_16));
      break;
    case compare32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case compare64:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case test32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case test64:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case compareDouble:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case compareFloat:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
      break;
    case branch8:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_8));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_8));
      break;
    case branch32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      break;
    case branch64:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      break;
    case branchTest8:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_8));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_8));
      break;
    case branchTest32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      break;
    case branchTest64:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      break;
    case branchDouble:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      break;
    case branchFloat:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
      break;
    case branchAdd32:
      switch (inst._args.length) {
        case INST_COUNT_NUM_4:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
          break;
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_32));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case branchAdd64:
      switch (inst._args.length) {
        case INST_COUNT_NUM_4:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_64));
          break;
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_64));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case branchMul32:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_32));
          break;
        case INST_COUNT_NUM_4:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
          break;
        case INST_COUNT_NUM_6:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.scratch, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.scratch, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_5, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_32));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case branchMul64:
      switch (inst._args.length) {
        case INST_COUNT_NUM_3:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_64));
          break;
        case INST_COUNT_NUM_6:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.scratch, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.scratch, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_5, fun, new InstDateModel(Arg.zDef, GP, INST_WIDTH_NUM_64));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case branchSub32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_32));
      break;
    case branchSub64:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.useDef, GP, INST_WIDTH_NUM_64));
      break;
    case branchNeg32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_32));
      break;
    case branchNeg64:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.useZDef, GP, INST_WIDTH_NUM_64));
      break;
    case moveConditionally32:
      switch (inst._args.length) {
        case INST_COUNT_NUM_5:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.useDef, GP, PTR));
          break;
        case INST_COUNT_NUM_6:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_5, fun, new InstDateModel(Arg.def, GP, PTR));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case moveConditionally64:
      switch (inst._args.length) {
        case INST_COUNT_NUM_5:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.useDef, GP, PTR));
          break;
        case INST_COUNT_NUM_6:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_5, fun, new InstDateModel(Arg.def, GP, PTR));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case moveConditionallyTest32:
      switch (inst._args.length) {
        case INST_COUNT_NUM_5:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.useDef, GP, PTR));
          break;
        case INST_COUNT_NUM_6:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_5, fun, new InstDateModel(Arg.def, GP, PTR));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case moveConditionallyTest64:
      switch (inst._args.length) {
        case INST_COUNT_NUM_5:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.useDef, GP, PTR));
          break;
        case INST_COUNT_NUM_6:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_5, fun, new InstDateModel(Arg.def, GP, PTR));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case moveConditionallyDouble:
      switch (inst._args.length) {
        case INST_COUNT_NUM_6:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_5, fun, new InstDateModel(Arg.def, GP, PTR));
          break;
        case INST_COUNT_NUM_5:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
          inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.useDef, GP, PTR));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case moveConditionallyFloat:
      switch (inst._args.length) {
        case INST_COUNT_NUM_6:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_5, fun, new InstDateModel(Arg.def, GP, PTR));
          break;
        case INST_COUNT_NUM_5:
          inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
          inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
          inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, GP, PTR));
          inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.useDef, GP, PTR));
          break;
        default:
          throw Error('Bad overload');
      }
      break;
    case moveDoubleConditionally32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_5, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
      break;
    case moveDoubleConditionally64:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_5, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
      break;
    case moveDoubleConditionallyTest32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_5, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
      break;
    case moveDoubleConditionallyTest64:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_5, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
      break;
    case moveDoubleConditionallyDouble:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_5, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
      break;
    case moveDoubleConditionallyFloat:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      inst.visitArg(1, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_2, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
      inst.visitArg(INST_COUNT_NUM_3, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_4, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      inst.visitArg(INST_COUNT_NUM_5, fun, new InstDateModel(Arg.def, FP, INST_WIDTH_NUM_64));
      break;
    case jump:
      break;
    case ret32:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_32));
      break;
    case ret64:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, GP, INST_WIDTH_NUM_64));
      break;
    case retFloat:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_32));
      break;
    case retDouble:
      inst.visitArg(0, fun, new InstDateModel(Arg.use, FP, INST_WIDTH_NUM_64));
      break;
    case oops:
      break;
    case shuffle:
      ShuffleCustom.forEachArg(inst, fun);
      break;
    case patch:
      PatchCustom.forEachArg(inst, fun);
      break;
    case cCall:
      CCallCustom.forEachArg(inst, fun);
      break;
    case coldCCall:
      ColdCCallCustom.forEachArg(inst, fun);
      break;
    default:
      break;
  }
}

export function instHasNonArgEffects(inst: Inst): boolean {
  switch (inst._opcode) {
    case branch8:
    case branch32:
    case branch64:
    case branchTest8:
    case branchTest32:
    case branchTest64:
    case branchDouble:
    case branchFloat:
    case branchAdd32:
    case branchAdd64:
    case branchMul32:
    case branchMul64:
    case branchSub32:
    case branchSub64:
    case branchNeg32:
    case branchNeg64:
    case jump:
    case ret32:
    case ret64:
    case retFloat:
    case retDouble:
    case oops:
      return true;
    case shuffle:
      return new ShuffleCustom().hasNonArgNonControlEffects(inst);
    case patch:
      return new PatchCustom().hasNonArgNonControlEffects(inst);
    case cCall:
      return new CCallCustom().hasNonArgNonControlEffects(inst);
    case coldCCall:
      return new ColdCCallCustom().hasNonArgNonControlEffects(inst);
    default:
      return false;
  }
}

export function opcodeCode(opcode: string): number {
  switch (opcode) {
    case absDouble:
      return 0;
    case absFloat:
      return 1;
    case add16:
      return INST_SOME_VALUE_2;
    case add32:
      return INST_SOME_VALUE_3;
    case add64:
      return INST_SOME_VALUE_4;
    case add8:
      return INST_SOME_VALUE_5;
    case addDouble:
      return INST_SOME_VALUE_6;
    case addFloat:
      return INST_SOME_VALUE_7;
    case and32:
      return INST_SOME_VALUE_8;
    case and64:
      return INST_SOME_VALUE_9;
    case andDouble:
      return INST_SOME_VALUE_10;
    case andFloat:
      return INST_SOME_VALUE_11;
    case branch32:
      return INST_SOME_VALUE_12;
    case branch64:
      return INST_SOME_VALUE_13;
    case branch8:
      return INST_SOME_VALUE_14;
    case branchAdd32:
      return INST_SOME_VALUE_15;
    case branchAdd64:
      return INST_SOME_VALUE_16;
    case branchDouble:
      return INST_SOME_VALUE_17;
    case branchFloat:
      return INST_SOME_VALUE_18;
    case branchMul32:
      return INST_SOME_VALUE_19;
    case branchMul64:
      return INST_SOME_VALUE_20;
    case branchNeg32:
      return INST_SOME_VALUE_21;
    case branchNeg64:
      return INST_SOME_VALUE_22;
    case branchSub32:
      return INST_SOME_VALUE_23;
    case branchSub64:
      return INST_SOME_VALUE_24;
    case branchTest32:
      return INST_SOME_VALUE_25;
    case branchTest64:
      return INST_SOME_VALUE_26;
    case branchTest8:
      return INST_SOME_VALUE_27;
    case cCall:
      return INST_SOME_VALUE_28;
    case ceilDouble:
      return INST_SOME_VALUE_29;
    case ceilFloat:
      return INST_SOME_VALUE_30;
    case coldCCall:
      return INST_SOME_VALUE_31;
    case compare32:
      return INST_SOME_VALUE_32;
    case compare64:
      return INST_SOME_VALUE_33;
    case compareDouble:
      return INST_SOME_VALUE_34;
    case compareFloat:
      return INST_SOME_VALUE_35;
    case convertDoubleToFloat:
      return INST_SOME_VALUE_36;
    case convertFloatToDouble:
      return INST_SOME_VALUE_37;
    case convertInt32ToDouble:
      return INST_SOME_VALUE_38;
    case convertInt32ToFloat:
      return INST_SOME_VALUE_39;
    case convertInt64ToDouble:
      return INST_SOME_VALUE_40;
    case convertInt64ToFloat:
      return INST_SOME_VALUE_41;
    case countLeadingZeros32:
      return INST_SOME_VALUE_42;
    case countLeadingZeros64:
      return INST_SOME_VALUE_43;
    case div32:
      return INST_SOME_VALUE_44;
    case div64:
      return INST_SOME_VALUE_45;
    case divDouble:
      return INST_SOME_VALUE_46;
    case divFloat:
      return INST_SOME_VALUE_47;
    case floorDouble:
      return INST_SOME_VALUE_48;
    case floorFloat:
      return INST_SOME_VALUE_49;
    case jump:
      return INST_SOME_VALUE_50;
    case lea:
      return INST_SOME_VALUE_51;
    case load16:
      return INST_SOME_VALUE_52;
    case load16SignedExtendTo32:
      return INST_SOME_VALUE_53;
    case load8:
      return INST_SOME_VALUE_54;
    case load8SignedExtendTo32:
      return INST_SOME_VALUE_55;
    case lshift32:
      return INST_SOME_VALUE_56;
    case lshift64:
      return INST_SOME_VALUE_57;
    case move:
      return INST_SOME_VALUE_58;
    case move32:
      return INST_SOME_VALUE_59;
    case move32ToFloat:
      return INST_SOME_VALUE_60;
    case move64ToDouble:
      return INST_SOME_VALUE_61;
    case moveConditionally32:
      return INST_SOME_VALUE_62;
    case moveConditionally64:
      return INST_SOME_VALUE_63;
    case moveConditionallyDouble:
      return INST_SOME_VALUE_64;
    case moveConditionallyFloat:
      return INST_SOME_VALUE_65;
    case moveConditionallyTest32:
      return INST_SOME_VALUE_66;
    case moveConditionallyTest64:
      return INST_SOME_VALUE_67;
    case moveDouble:
      return INST_SOME_VALUE_68;
    case moveDoubleConditionally32:
      return INST_SOME_VALUE_69;
    case moveDoubleConditionally64:
      return INST_SOME_VALUE_70;
    case moveDoubleConditionallyDouble:
      return INST_SOME_VALUE_71;
    case moveDoubleConditionallyFloat:
      return INST_SOME_VALUE_72;
    case moveDoubleConditionallyTest32:
      return INST_SOME_VALUE_73;
    case moveDoubleConditionallyTest64:
      return INST_SOME_VALUE_74;
    case moveDoubleTo64:
      return INST_SOME_VALUE_75;
    case moveFloat:
      return INST_SOME_VALUE_76;
    case moveFloatTo32:
      return INST_SOME_VALUE_77;
    case moveZeroToDouble:
      return INST_SOME_VALUE_78;
    case mul32:
      return INST_SOME_VALUE_79;
    case mul64:
      return INST_SOME_VALUE_80;
    case mulDouble:
      return INST_SOME_VALUE_81;
    case mulFloat:
      return INST_SOME_VALUE_82;
    case multiplyAdd32:
      return INST_SOME_VALUE_83;
    case multiplyAdd64:
      return INST_SOME_VALUE_84;
    case multiplyNeg32:
      return INST_SOME_VALUE_85;
    case multiplyNeg64:
      return INST_SOME_VALUE_86;
    case multiplySub32:
      return INST_SOME_VALUE_87;
    case multiplySub64:
      return INST_SOME_VALUE_88;
    case neg32:
      return INST_SOME_VALUE_89;
    case neg64:
      return INST_SOME_VALUE_90;
    case negateDouble:
      return INST_SOME_VALUE_91;
    case nop:
      return INST_SOME_VALUE_92;
    case not32:
      return INST_SOME_VALUE_93;
    case not64:
      return INST_SOME_VALUE_94;
    case oops:
      return INST_SOME_VALUE_95;
    case or32:
      return INST_SOME_VALUE_96;
    case or64:
      return INST_SOME_VALUE_97;
    case patch:
      return INST_SOME_VALUE_98;
    case ret32:
      return INST_SOME_VALUE_99;
    case ret64:
      return INST_SOME_VALUE_100;
    case retDouble:
      return INST_SOME_VALUE_101;
    case retFloat:
      return INST_SOME_VALUE_102;
    case rshift32:
      return INST_SOME_VALUE_103;
    case rshift64:
      return INST_SOME_VALUE_104;
    case shuffle:
      return INST_SOME_VALUE_105;
    case signExtend16To32:
      return INST_SOME_VALUE_106;
    case signExtend32ToPtr:
      return INST_SOME_VALUE_107;
    case signExtend8To32:
      return INST_SOME_VALUE_108;
    case sqrtDouble:
      return INST_SOME_VALUE_109;
    case sqrtFloat:
      return INST_SOME_VALUE_110;
    case store16:
      return INST_SOME_VALUE_111;
    case store8:
      return INST_SOME_VALUE_112;
    case storeZero32:
      return INST_SOME_VALUE_113;
    case sub32:
      return INST_SOME_VALUE_114;
    case sub64:
      return INST_SOME_VALUE_115;
    case subDouble:
      return INST_SOME_VALUE_116;
    case subFloat:
      return INST_SOME_VALUE_117;
    case swap32:
      return INST_SOME_VALUE_118;
    case swap64:
      return INST_SOME_VALUE_119;
    case test32:
      return INST_SOME_VALUE_120;
    case test64:
      return INST_SOME_VALUE_121;
    case urshift32:
      return INST_SOME_VALUE_122;
    case urshift64:
      return INST_SOME_VALUE_123;
    case x86ConvertToDoubleWord32:
      return INST_SOME_VALUE_124;
    case x86ConvertToQuadWord64:
      return INST_SOME_VALUE_125;
    case x86Div32:
      return INST_SOME_VALUE_126;
    case x86Div64:
      return INST_SOME_VALUE_127;
    case xor32:
      return INST_SOME_VALUE_128;
    case xor64:
      return INST_SOME_VALUE_129;
    case xorDouble:
      return INST_SOME_VALUE_130;
    case xorFloat:
      return INST_SOME_VALUE_131;
    case zeroExtend16To32:
      return INST_SOME_VALUE_132;
    case zeroExtend8To32:
      return INST_SOME_VALUE_133;
    default:
      throw Error('bad opcode');
  }
}
